/*-
 * DaermaBusinessProcessor.java
 *
 * Date: 2017年3月10日
 * Time: 下午2:41:34
 *
 * 版权所有©2012-2013 rengh
 */

package com.lmx.thirdPart.daerma;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import javax.annotation.PostConstruct;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;

import com.lmx.common.constants.CommonConstants;
import com.lmx.common.context.ActionContextHolder;
import com.lmx.common.util.CommonUtil;
import com.lmx.common.util.PropertiesFileUtil;
import com.lmx.persistence.service.CommonService;
import com.lmx.persistence.service.DeviceService;
import com.lmx.persistence.service.HealthInfoService;
import com.lmx.repoDomain.tmodel.Customer;
import com.lmx.repoDomain.tmodel.CustomerDevice;
import com.lmx.repoDomain.tmodel.Device;
import com.lmx.repoDomain.tmodel.Dicttype;
import com.lmx.repoDomain.tmodel.HealthInfo;
import com.lmx.repoDomain.tmodel.Message;
import com.lmx.thirdPart.BusinessProcessor;
import com.lmx.thirdPart.ThirdPartBusiException;
import com.lmx.thirdPart.ThirdPartProcessor;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;


/**
 * 大耳马业务处理实现类
 * 
 * @author lmx
 * @version 1.00
 */
@Service
@Scope("singleton")
public class DaermaBusinessProcessor extends ThirdPartProcessor implements BusinessProcessor {
    //设备状态码
    public static Integer DEVICESTATUS_OFFBED = 3;//离床
    public static Integer DEVICESTATUS_ONBED = 4;//在床
    public static Integer DEVICESTATUS_OFFLINE = 6;//设备断线
    
	private static Log logger = LogFactory.getLog(DaermaBusinessProcessor.class);
	
	@Autowired
	protected DeviceService deviceService;
    @Autowired
    protected CommonService commonService;
    @Autowired
    protected HealthInfoService healthInfoService;
    
	String con = null;//厂商方本公司的标识号
	String url = null;//请求地址
	String token = null;//令牌
	Integer expireTime = null;//超时时间
	Integer statusStartTime = 0;//状态查询起始时间
	//正在登录的标志
	private boolean loginFlag = false;
	
    @PostConstruct
    public void init() {
        Properties properties = PropertiesFileUtil.getProperties("application.properties");
    	cm =new PoolingHttpClientConnectionManager();
	    cm.setMaxTotal(Integer.parseInt(properties.getProperty("http.connectPool.max")));
	    cm.setDefaultMaxPerRoute(Integer.parseInt(properties.getProperty("http.connectPool.maxPerRoute")));
	    this.client=HttpClients.custom().setConnectionManager(cm).build();
        //this.client = HttpClients.createDefault();
        this.url = "http://mattress.darma.cn/mattress/ws";
        this.con = properties.getProperty("thirdPart.daerma.con");
    }	

    public String buisPost(String url, String argument)
            throws ClientProtocolException, IOException,ThirdPartBusiException{
        Map<String, String> header = new HashMap<>();
        header.put("Content-Type", "application/json");
        //需要预先进行登录或判断
        this.preLogin();
        header.put("access_token",this.token);
        return this.post(url, header, argument);
    }
    public String buisGet(String url, String argument)
            throws ClientProtocolException, IOException,ThirdPartBusiException{
        Map<String, String> header = new HashMap<>();
        header.put("access_token",this.token);
        header.put("Content-Type", "application/json");
        //需要预先进行登录或判断
        this.preLogin();
        return this.get(url, header, argument);
    }   
    
   /*
    * 处理预登录
    */
	@Override
    public void preLogin() throws ThirdPartBusiException{
        if(this.token==null){
            this.login();
            return;
        }
        int sysTime = new Long(new Date().getTime()/1000).intValue();
        //在超时到来前1000秒进行登录
        logger.debug("this.expireTime:" + this.expireTime + " and sys time:" + sysTime);
        if(this.expireTime.intValue()-sysTime<1000){
            //如果正在有线程进行登录操作，则不执行登录
            if(this.loginFlag){
              //等待2秒后，检查是否登录完毕，决定是否下一步。最多等3次.
              for(int i=0;i<3;i++){
                  if(this.loginFlag){
                      try {
                        Thread.sleep(2000);
                    } catch (InterruptedException e) {
                        logger.warn("sleep err",e);
                    }
                  }else{
                      break;
                  }
              }
            }else{
                this.login(); 
            }
            
        }
    }
    
	/*
	 * 进行登录
	 */
	public synchronized void login() throws ThirdPartBusiException{
	    //设置登录标志，以锁定后续重复登录操作
	    this.loginFlag = true;
        Map<String, String> map = new HashMap<>();
        map.put("access_token", "c827aff21cf6407a8ccfe2212fc19fd4");
        map.put("Content-Type", "application/json");
        map.put("v", "1.0");
        JSONObject params = new JSONObject();
        params.put("scope", "default");
        params.put("user_name", "yunbao");
        params.put("password", "123456");
        params.put("grant_type", "password");
        try {
            String tokenRes = this.post(this.url + "/authorize", map, params.toString());
            logger.debug("tokenRes:" + tokenRes);
            JSONObject res = JSONObject.fromObject(tokenRes);
            //处理异常
            if(res.get("error_response")!=null){
                throw new ThirdPartBusiException(res.getString("code"),res.getString("sub_code"));
            }
            //保存token
            this.token = res.getJSONObject("authorize").getString("access_token");
            Integer authTime = res.getJSONObject("authorize").getInt("authorize_time");
            Integer expiresIn = res.getJSONObject("authorize").getInt("expires_in");
            //记录超时时间
            expireTime = new Integer(authTime.intValue()+expiresIn.intValue());
        } catch (IOException e) {
            logger.error("login io fail",e);
            throw new ThirdPartBusiException(1);
        } finally{
            this.loginFlag = false;
        }
	}

	/*
	 * 获取设备30秒数据
	 */
	@Override
	public void getDeviceStatus() throws ThirdPartBusiException {
		List infoList = new ArrayList();
		List deviceList = new ArrayList();
		JSONObject params = new JSONObject();
		String deviceNosTemp="";
		String deviceNos="";
		List<CustomerDevice> cdList=deviceService.getAllBedMat();
		if (cdList == null && cdList.size() == 0) {
			return;
		} else {
			for (CustomerDevice cd : cdList) {
				if (cd != null && cd.getDevice() != null) {
					deviceNosTemp += "," + cd.getDevice().getSeq();
				}
			}
			if (deviceNosTemp.length() > 0) {
				deviceNos += deviceNosTemp.substring(1, deviceNosTemp.length());
			}
		}
		params.put("queryType", "queryLastData");
		params.put("startTime", new Long(new Date().getTime() / 1000).toString());
		params.put("endTime", new Long(new Date().getTime() / 1000).toString());
		params.put("deviceNos", deviceNos);
		try {
			String res = this.buisPost(this.url + "/healthdata/device?con=" + this.con, params.toString());
			 //String res =this.buisPost("http://124.42.9.27:7080/access/test/daerma",params.toString());
//			 res = "{\"retCode\": 0,\"message\": \"test\"," 
//			        + "\"data\": {"
//					+ "\"641650000017\": {"
//					+ "\"heart\":[{\"markTime\": 1487744454,\"val\": 100" + "}],\"status\": [{\"markTime\": 1487744454," + "\"val\": 6}]," 
//					+ "\"motion\":[]," 
//					+ "\"breath\":[{\"markTime\": 1487744483,\"val\": 10" + "}]}," 
//					+ "\"646D626400A8\":{\"heart\": [{\"markTime\": 1487744483,\"val\": 100}],\"status\": [{\"markTime\":1487744454,\"val\": 6}],"
//					+ "\"motion\": [],"
//					+ "\"breath\":[{\"markTime\":1487744454,\"val\": 10},{\"markTime\": 1487744483,\"val\": 11}]"
//					+ "}}}";
			logger.debug("getDeviceStatus res:" + res);
			JSONObject resObj = JSONObject.fromObject(res);
			// 处理异常
			if (resObj.get("error_response") != null) {
				throw new ThirdPartBusiException(resObj.getJSONObject("error_response").getString("code"),
						resObj.getJSONObject("error_response").getString("sub_code"));
			}
			Integer retCode = resObj.getInt("retCode");
			JSONArray deviceStatus = new JSONArray();
			// code为0表示正常返回
			if (retCode.intValue() == 0) {
				String message = resObj.getString("message");
				JSONObject dataNode = resObj.getJSONObject("data");
				Iterator<String> it = dataNode.keys();
				while (it.hasNext()) {
					// key就是设备号
					String deviceNo = it.next();
					JSONObject item = dataNode.getJSONObject(deviceNo);
					JSONObject ds = new JSONObject();
					ds.put("deviceNo", deviceNo);
					// 取得设备状态，更新设备信息
					JSONArray statusData = item.getJSONArray("status");
					if (statusData.size() > 0) {
						Integer val = statusData.getJSONObject(0).getInt("val");
						// 设备信息获取
						ds.put("status", val);
						deviceStatus.add(ds);
					}
					// 信号数据
					// System.out.println(item.getString("motion"));
					if (item.containsKey("signal") && !"[]".equals(item.getString("signal"))) {
						JSONArray signalData = item.getJSONArray("signal");
						if (signalData.size() > 0) {
							Integer val = statusData.getJSONObject(0).getInt("val");
							// 设备信息获取
							ds.put("signal", val);
							deviceStatus.add(ds);
						}
					}
					Customer customer = this.deviceService.getCustomerWithDeviceNo(deviceNo);
					Device device = this.deviceService.getDeviceWithDeviceNo(deviceNo);
					if(device!=null){
						// 修改设备信息
						if (customer != null) {// 已绑定
							device.setStatus(commonService.getDicttype(CommonConstants.DICTTYPE.DEVICE_STATUS_2.label()));// 已占用
						} else {
							device.setStatus(commonService.getDicttype(CommonConstants.DICTTYPE.DEVICE_STATUS_1.label()));
						}
						device.setStatusDate(CommonUtil.getCurrTimes());//设置设备状态时间
						device.setDeviceStatus((short)1);
						deviceList.add(device);
					}
					if (customer != null) {
						// 取得心率数据，更新相关信息
						if (item.containsKey("heart") && !"[]".equals(item.getString("heart"))) {
							JSONArray heartData = item.getJSONArray("heart");
							if (heartData.size() > 0) {
								// for(int i=0;i<heartData.size();i++){
								// 只取时间最近的那条
								for (int i = heartData.size() - 1; i < heartData.size()&&i>=0; i--) {
									Integer val = heartData.getJSONObject(i).getInt("val");
									if (val == -100 || val == 65436) {// 无效数据
										continue;
									} else {
										HealthInfo info = new HealthInfo();
										info.setExamUser(customer);
										info.setDelStatus((short) 0);
										info.setTenant(customer.getTenant());
										info.setDevice(device);// huibati
										// info.setExamDateTime(CommonUtil.getCurrTimes());
										info.setExamDateTime(heartData.getJSONObject(i).getInt("markTime"));
										info.setCreateDateTime((long)CommonUtil.getCurrTimes());
										// 处理健康类业务数据
										// TODO
										info.setResult(val.toString());
										// 组装并发送消息
										Dicttype rateType = commonService
												.getDicttype(CommonConstants.DICTTYPE.HEALTHEXAMTYPE_RATE.label());
										info.setItemtype(rateType);
										info.setResult(val.toString());
										info.setSourceFlag("fromDevice");
										Message msgObj = this.buildHealthMessage(customer, info);
										// 发送给队列管理器
										if (msgObj.getUserList() != null && msgObj.getUserList().size() > 0) {
											ActionContextHolder.getMessageQueue().addMessage(msgObj);// huibati
										}
										// healthInfoService.createHealthInfo(info);
										infoList.add(info);
										healthInfoService.createMessages(msgObj);
										break;
									}
								}
							}
						}
						// 体动数据
						if (item.containsKey("motion") && !"[]".equals(item.getString("motion"))) {
							JSONArray motionData = item.getJSONArray("motion");
						}
						// 呼吸数据
						if (item.containsKey("breath") && !"[]".equals(item.getString("breath"))) {
							JSONArray breathData = item.getJSONArray("breath");
							if (breathData.size() > 0) {
								//for(int i=0;i<breathData.size();i++){
								//只取时间最近的那条
								for (int i = breathData.size() - 1; i < breathData.size()&&i>=0; i--) {
									Integer val = breathData.getJSONObject(i).getInt("val");
									if (val == -100 || val == 65436) {// 无效数据
										continue;
									} else {
										HealthInfo info = new HealthInfo();
										info.setExamUser(customer);
										info.setDelStatus((short) 0);
										info.setTenant(customer.getTenant());
										info.setDevice(device);// huibati
										// info.setExamDateTime(CommonUtil.getCurrTimes());
										info.setExamDateTime(breathData.getJSONObject(i).getInt("markTime"));
										info.setCreateDateTime((long)CommonUtil.getCurrTimes());
										// 处理健康类业务数据
										// TODO
										info.setResult(val.toString());
										// 组装并发送消息
										Dicttype breathType = commonService
												.getDicttype(CommonConstants.DICTTYPE.HEALTHEXAMTYPE_BREATH.label());
										info.setItemtype(breathType);
										info.setResult(val.toString());
										info.setSourceFlag("fromDevice");
										Message msgObj = this.buildHealthMessage(customer, info);
										// 发送给队列管理器
										if (msgObj.getUserList() != null && msgObj.getUserList().size() > 0) {
											ActionContextHolder.getMessageQueue().addMessage(msgObj);// huibati
										}
										// healthInfoService.createHealthInfo(info);
										infoList.add(info);
										healthInfoService.createMessages(msgObj);
										break;
									}
								}
							}//呼吸数据
						}
					}
				}
				if(infoList.size()>0){
					commonService.batchInsert(infoList);//add 健康数据
				}
				if(deviceList.size()>0){
				    commonService.batchUpdate(deviceList);//更新设备时间
				}
			}
		} catch (IOException e) {
			logger.error("login io fail", e);
		} finally {
			this.loginFlag = false;
		}
	}

	/*
	 * 用户行为
	 * @params deviceNo 对应用户的设备编号
	 */
	public void getManBehaveData(String deviceNo) throws ThirdPartBusiException{
        JSONObject params = new JSONObject();
        //取得用户的所有数据（呼吸，心率，睡眠状态）
        params.put("start_time", Integer.toString(CommonUtil.getDayBegin()));
        params.put("end_time", new Long(new Date().getTime()/1000).toString());
        try {
            String res = this.buisGet(this.url + "/manBehaveData/0/"+deviceNo,params.toString());
            logger.debug("getManBehaveData res:" + res);
            JSONObject resObj = JSONObject.fromObject(res);
            //处理异常
            if(resObj.get("error_response")!=null){
                throw new ThirdPartBusiException(resObj.getJSONObject("error_response").getString("code"),resObj.getJSONObject("error_response").getString("sub_code"));
            }
            Integer retCode = resObj.getInt("retCode");

        } catch (IOException e) {
            logger.error("login io fail",e);
        } finally{
            this.loginFlag = false;
        }
	}

	/*
	 * 获取离床通知 http://124.42.9.27:7090
	 */
	public String geLeavingBed() {
		// AppLogger.getInstance().infoLog("xmlParam:" + xmlParam);
		CloseableHttpClient client = HttpClients.createDefault();
		HttpGet req = new HttpGet("http://localhost:9080/thirdPart/leavingBed");
		// req.setHeader("Content-type", "application/json");
		try {
			HttpResponse response = client.execute(req);
			String jsonStr = EntityUtils.toString(response.getEntity(), "UTF-8");
			logger.debug("jsonStr:" + jsonStr);
			return jsonStr;
		} catch (Exception e) {
			logger.error("LeavingBed fail:", e);
		}
		return null;
	}  


}
